package com.hospital.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hospital.entity.Registration;
import com.hospital.entity.User;
import com.hospital.entity.Department;
import com.hospital.entity.Schedule;
import com.hospital.mapper.RegistrationMapper;
import com.hospital.service.RegistrationService;
import com.hospital.service.UserService;
import com.hospital.service.DepartmentService;
import com.hospital.service.ScheduleService;
import com.hospital.util.UserContext;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.Random;

/**
 * 挂号服务实现类
 *
 * @author Hospital Management System
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RegistrationServiceImpl extends ServiceImpl<RegistrationMapper, Registration> implements RegistrationService {

    private final UserService userService;
    private final DepartmentService departmentService;
    private final ScheduleService scheduleService;

    @Override
    public List<Registration> getDoctorRegistrations(String date) {
        Long currentDoctorId = UserContext.getCurrentUser().getId();
        QueryWrapper<Registration> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("doctor_id", currentDoctorId)
                   .eq("deleted", 0);
        
        if (StringUtils.hasText(date)) {
            // 按日期查询
            try {
                LocalDate appointmentDate = LocalDate.parse(date);
                queryWrapper.eq("appointment_date", appointmentDate);
            } catch (Exception e) {
                log.warn("日期格式错误: {}", date);
            }
        }
        
        List<Registration> registrations = list(queryWrapper);
        fillRelatedInfo(registrations);
        return registrations;
    }

    @Override
    public Map<String, Object> getRegistrations(String keyword, Integer status, Integer type, 
                                              LocalDate appointmentDate, Long departmentId,
                                              Integer page, Integer size) {
        log.info("开始查询挂号列表，参数：keyword={}, status={}, type={}, appointmentDate={}, departmentId={}, page={}, size={}", 
                 keyword, status, type, appointmentDate, departmentId, page, size);
        
        // 创建分页对象
        Page<Registration> pageObj = new Page<>(page, size);
        
        // 构建查询条件
        QueryWrapper<Registration> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("deleted", 0);
        
        try {
            // 添加关键词搜索
            if (StringUtils.hasText(keyword)) {
                log.info("处理关键词搜索条件: {}", keyword);
                // 先查询匹配关键词的用户
                QueryWrapper<User> userQuery = new QueryWrapper<>();
                userQuery.like("name", keyword)
                        .or()
                        .like("phone", keyword)
                        .or()
                        .like("id_card", keyword);
                List<User> users = userService.list(userQuery);
                List<Long> userIds = users.stream()
                                        .map(User::getId)
                                        .collect(Collectors.toList());
                log.info("找到匹配关键词的用户数量: {}", userIds.size());

                // 再查询匹配关键词的医生
                QueryWrapper<User> doctorQuery = new QueryWrapper<>();
                doctorQuery.like("name", keyword)
                          .eq("role", 2); // 确保只查询医生角色
                List<User> doctors = userService.list(doctorQuery);
                List<Long> doctorIds = doctors.stream()
                                            .map(User::getId)
                                            .collect(Collectors.toList());
                log.info("找到匹配关键词的医生数量: {}", doctorIds.size());

                // 查询匹配关键词的科室
                QueryWrapper<Department> deptQuery = new QueryWrapper<>();
                deptQuery.like("name", keyword);
                List<Department> departments = departmentService.list(deptQuery);
                List<Long> deptIds = departments.stream()
                                              .map(Department::getId)
                                              .collect(Collectors.toList());
                log.info("找到匹配关键词的科室数量: {}", deptIds.size());

                // 组合查询条件
                queryWrapper.and(wrapper -> {
                    if (!userIds.isEmpty()) {
                        wrapper.in("user_id", userIds);
                    }
                    if (!doctorIds.isEmpty()) {
                        wrapper.or().in("doctor_id", doctorIds);
                    }
                    if (!deptIds.isEmpty()) {
                        wrapper.or().in("department_id", deptIds);
                    }
                    wrapper.or().like("registration_no", keyword)
                           .or().like("remark", keyword);
                });
            }
            
            // 添加状态筛选
            if (status != null) {
                log.info("添加状态筛选条件: {}", status);
                queryWrapper.eq("status", status);
            }
            
            // 添加类型筛选
            if (type != null) {
                log.info("添加类型筛选条件: {}", type);
                queryWrapper.eq("type", type);
            }
            
            // 添加预约日期筛选
            if (appointmentDate != null) {
                log.info("添加预约日期筛选条件: {}", appointmentDate);
                queryWrapper.eq("appointment_date", appointmentDate);
            }
            
            // 添加科室筛选
            if (departmentId != null) {
                log.info("添加科室筛选条件: {}", departmentId);
                queryWrapper.eq("department_id", departmentId);
            }
            
            // 打印最终的SQL语句
            String sqlSegment = queryWrapper.getSqlSegment();
            log.info("最终的SQL条件: {}", sqlSegment);
            
            // 按创建时间降序排序
            queryWrapper.orderByDesc("create_time");
            
            // 执行分页查询
            IPage<Registration> pageResult = page(pageObj, queryWrapper);
            
            // 获取分页数据
            List<Registration> registrations = pageResult.getRecords();
            log.info("查询结果总数: {}", pageResult.getTotal());
            
            // 填充关联信息
            fillRelatedInfo(registrations);
            
            // 构建返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("list", registrations);
            result.put("total", pageResult.getTotal());
            result.put("page", pageResult.getCurrent());
            result.put("size", pageResult.getSize());
            result.put("pages", pageResult.getPages());
            
            return result;
        } catch (Exception e) {
            log.error("查询挂号列表时发生错误: {}", e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 填充关联信息（患者姓名、医生姓名、科室名称）
     */
    @Override
    public void fillRelatedInfo(List<Registration> registrations) {
        if (registrations == null || registrations.isEmpty()) {
            return;
        }

        // 收集所有需要查询的ID
        List<Long> userIds = registrations.stream()
                .map(Registration::getUserId)
                .distinct()
                .collect(Collectors.toList());

        List<Long> doctorIds = registrations.stream()
                .map(Registration::getDoctorId)
                .distinct()
                .collect(Collectors.toList());

        List<Long> departmentIds = registrations.stream()
                .map(Registration::getDepartmentId)
                .distinct()
                .collect(Collectors.toList());

        // 批量查询
        Map<Long, User> userMap = new HashMap<>();
        if (!userIds.isEmpty()) {
            List<User> users = userService.listByIds(userIds);
            userMap = users.stream()
                    .collect(Collectors.toMap(User::getId, user -> user));
        }

        Map<Long, User> doctorMap = new HashMap<>();
        if (!doctorIds.isEmpty()) {
            List<User> doctors = userService.listByIds(doctorIds);
            doctorMap = doctors.stream()
                    .collect(Collectors.toMap(User::getId, doctor -> doctor));
        }

        Map<Long, Department> departmentMap = new HashMap<>();
        if (!departmentIds.isEmpty()) {
            List<Department> departments = departmentService.listByIds(departmentIds);
            departmentMap = departments.stream()
                    .collect(Collectors.toMap(Department::getId, dept -> dept));
        }

        // 填充信息
        for (Registration registration : registrations) {
            // 设置患者姓名
            if (registration.getUserId() != null && userMap.containsKey(registration.getUserId())) {
                registration.setUserName(userMap.get(registration.getUserId()).getName());
            }

            // 设置医生姓名
            if (registration.getDoctorId() != null && doctorMap.containsKey(registration.getDoctorId())) {
                registration.setDoctorName(doctorMap.get(registration.getDoctorId()).getName());
            }

            // 设置科室名称
            if (registration.getDepartmentId() != null && departmentMap.containsKey(registration.getDepartmentId())) {
                registration.setDepartmentName(departmentMap.get(registration.getDepartmentId()).getName());
            }
        }
    }

    @Override
    @Transactional
    public void makeAppointment(Registration registration) {
        // 获取当前用户
        User currentUser = UserContext.getCurrentUser();
        if (currentUser == null) {
            throw new RuntimeException("用户未登录");
        }

        // 检查排班是否存在且有效
        Schedule schedule = scheduleService.getById(registration.getScheduleId());
        if (schedule == null) {
            throw new RuntimeException("该排班不存在");
        }

        // 检查剩余号源
        int remainingQuota = schedule.getAvailableCount() - (schedule.getBookedCount() != null ? schedule.getBookedCount() : 0);
        if (remainingQuota <= 0) {
            throw new RuntimeException("该时段已无剩余号源");
        }

        // 检查是否重复预约
        QueryWrapper<Registration> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", currentUser.getId())
                   .eq("doctor_id", registration.getDoctorId())
                   .eq("appointment_date", registration.getAppointmentDate())
                   .eq("appointment_time", registration.getAppointmentTime())
                   .eq("status", 0); // 检查是否有未完成的预约
        
        if (count(queryWrapper) > 0) {
            throw new RuntimeException("您已预约过该时段");
        }

        // 生成挂号编号：REG + 年月日 + 6位随机数
        String registrationNo = "REG" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"))
                + String.format("%06d", new Random().nextInt(999999));
        
        // 设置挂号信息
        registration.setRegistrationNo(registrationNo);
        registration.setUserId(currentUser.getId());
        registration.setStatus(0); // 已预约
        registration.setPaymentStatus(0); // 未支付
        registration.setCreateTime(LocalDateTime.now());
        registration.setUpdateTime(LocalDateTime.now());
        registration.setDeleted(0);

        // 保存挂号记录
        if (!save(registration)) {
            throw new RuntimeException("保存挂号记录失败，请重试");
        }

        // 更新排班信息
        schedule.setBookedCount(schedule.getBookedCount() != null ? schedule.getBookedCount() + 1 : 1);
        // 如果已预约数等于可预约数，设置状态为已满
        if (schedule.getBookedCount() >= schedule.getAvailableCount()) {
            schedule.setStatus(2); // 设置为已满状态
        }
        if (!scheduleService.updateById(schedule)) {
            throw new RuntimeException("更新排班信息失败，请重试");
        }

        log.info("预约挂号成功 - 挂号编号: {}, 患者ID: {}, 医生ID: {}, 剩余号源: {}", 
                 registrationNo, currentUser.getId(), registration.getDoctorId(), 
                 schedule.getAvailableCount() - schedule.getBookedCount());
    }

    @Override
    public void cancelRegistration(Long registrationId) {
        Registration registration = getById(registrationId);
        if (registration != null) {
            // 设置为取消状态
            registration.setStatus(2); // 已取消状态
            updateById(registration);
            log.info("取消挂号成功，挂号ID: {}", registrationId);
        }
    }

    @Override
    public List<Registration> getUserRegistrations() {
        Long currentUserId = UserContext.getCurrentUser().getId();
        QueryWrapper<Registration> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", currentUserId)
                   .eq("deleted", 0);
        log.info("查询用户挂号记录，用户ID: {}", currentUserId);
        return list(queryWrapper);
    }

    @Override
    public long countTodayRegistrations() {
        QueryWrapper<Registration> queryWrapper = new QueryWrapper<>();
        LocalDate today = LocalDate.now();
        queryWrapper.eq("appointment_date", today)
                   .eq("deleted", 0);
        return count(queryWrapper);
    }

    @Override
    public double calculateRegistrationGrowth() {
        // 获取今日和昨日的挂号数
        LocalDate today = LocalDate.now();
        LocalDate yesterday = today.minusDays(1);

        QueryWrapper<Registration> todayQuery = new QueryWrapper<>();
        todayQuery.eq("appointment_date", today)
                 .eq("deleted", 0);
        long todayCount = count(todayQuery);

        QueryWrapper<Registration> yesterdayQuery = new QueryWrapper<>();
        yesterdayQuery.eq("appointment_date", yesterday)
                     .eq("deleted", 0);
        long yesterdayCount = count(yesterdayQuery);

        // 计算增长率
        if (yesterdayCount == 0) {
            return todayCount > 0 ? 100.0 : 0.0;
        }
        return ((double) (todayCount - yesterdayCount) / yesterdayCount) * 100;
    }

    @Override
    public Map<String, Object> getRegistrationTrend(LocalDate startDate, LocalDate endDate) {
        QueryWrapper<Registration> queryWrapper = new QueryWrapper<>();
        queryWrapper.between("appointment_date", startDate, endDate)
                   .eq("deleted", 0)
                   .orderByAsc("appointment_date");
        
        List<Registration> registrations = list(queryWrapper);
        
        // 按日期分组统计
        Map<LocalDate, Long> dailyCounts = registrations.stream()
                .collect(Collectors.groupingBy(Registration::getAppointmentDate, Collectors.counting()));
        
        // 准备返回数据
        List<String> dates = new ArrayList<>();
        List<Long> counts = new ArrayList<>();
        
        // 填充数据（包括没有挂号的日期，计数为0）
        LocalDate date = startDate;
        while (!date.isAfter(endDate)) {
            dates.add(date.format(DateTimeFormatter.ISO_LOCAL_DATE));
            counts.add(dailyCounts.getOrDefault(date, 0L));
            date = date.plusDays(1);
        }
        
        Map<String, Object> result = new HashMap<>();
        result.put("dates", dates);
        result.put("counts", counts);
        return result;
    }

    @Override
    public List<Map<String, Object>> getDepartmentDistribution() {
        // 获取最近30天的挂号数据
        LocalDate endDate = LocalDate.now();
        LocalDate startDate = endDate.minusDays(30);
        
        QueryWrapper<Registration> queryWrapper = new QueryWrapper<>();
        queryWrapper.between("appointment_date", startDate, endDate)
                   .eq("deleted", 0);
        
        List<Registration> registrations = list(queryWrapper);
        
        // 按科室分组统计
        Map<Long, Long> departmentCounts = registrations.stream()
                .collect(Collectors.groupingBy(Registration::getDepartmentId, Collectors.counting()));
        
        // 查询科室信息
        List<Department> departments = departmentService.listByIds(departmentCounts.keySet());
        Map<Long, String> departmentNames = departments.stream()
                .collect(Collectors.toMap(Department::getId, Department::getName));
        
        // 构建返回数据
        return departmentCounts.entrySet().stream()
                .map(entry -> {
                    Map<String, Object> item = new HashMap<>();
                    item.put("value", entry.getValue());
                    item.put("name", departmentNames.get(entry.getKey()));
                    return item;
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<Map<String, Object>> getRealtimeRegistrations() {
        // 获取最近2小时的挂号记录
        LocalDateTime endTime = LocalDateTime.now();
        LocalDateTime startTime = endTime.minusHours(2);
        
        QueryWrapper<Registration> queryWrapper = new QueryWrapper<>();
        queryWrapper.between("create_time", startTime, endTime)
                   .eq("deleted", 0)
                   .orderByDesc("create_time")
                   .last("LIMIT 5");  // 最多返回5条记录
        
        List<Registration> registrations = list(queryWrapper);
        fillRelatedInfo(registrations);  // 填充关联信息
        
        // 构建返回数据
        return registrations.stream()
                .map(reg -> {
                    Map<String, Object> item = new HashMap<>();
                    item.put("id", reg.getId());
                    item.put("patientName", reg.getUserName());
                    item.put("doctorName", reg.getDoctorName());
                    item.put("departmentName", reg.getDepartmentName());
                    item.put("time", reg.getCreateTime().format(DateTimeFormatter.ofPattern("HH:mm")));
                    return item;
                })
                .collect(Collectors.toList());
    }
} 